package com.segment.analytics; import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.util.Pair; import com.segment.analytics.internal.Private; import com.segment.analytics.internal.Utils; import java.util.Collections; import java.util.HashMap; import java.util.Map; class Stats { private static final String STATS_THREAD_NAME = Utils.THREAD_PREFIX + "Stats"; final HandlerThread statsThread; final StatsHandler handler; long flushCount; long flushEventCount; long integrationOperationCount; long integrationOperationDuration; Map<String, Long> integrationOperationDurationByIntegration = new HashMap<>(); Stats() { statsThread = new HandlerThread(STATS_THREAD_NAME, THREAD_PRIORITY_BACKGROUND); statsThread.start(); handler = new StatsHandler(statsThread.getLooper(), this); } void shutdown() { statsThread.quit(); } void dispatchFlush(int eventCount) { handler.sendMessage( handler // .obtainMessage(StatsHandler.TRACK_FLUSH, eventCount, 0)); } void performFlush(int eventCount) { flushCount++; flushEventCount += eventCount; } void dispatchIntegrationOperation(String key, long duration) { handler.sendMessage( handler // .obtainMessage(StatsHandler.TRACK_INTEGRATION_OPERATION, new Pair<>(key, duration))); } void performIntegrationOperation(Pair<String, Long> durationForIntegration) { integrationOperationCount++; integrationOperationDuration += durationForIntegration.second; Long duration = integrationOperationDurationByIntegration.get(durationForIntegration.first); if (duration == null) { integrationOperationDurationByIntegration.put( durationForIntegration.first, durationForIntegration.second); } else { integrationOperationDurationByIntegration.put( durationForIntegration.first, duration + durationForIntegration.second); } } StatsSnapshot createSnapshot() { return new StatsSnapshot( System.currentTimeMillis(), flushCount, flushEventCount, integrationOperationCount, integrationOperationDuration, Collections.unmodifiableMap(integrationOperationDurationByIntegration)); } private static class StatsHandler extends Handler { @Private static final int TRACK_FLUSH = 1; @Private static final int TRACK_INTEGRATION_OPERATION = 2; private final Stats stats; StatsHandler(Looper looper, Stats stats) { super(looper); this.stats = stats; } @Override public void handleMessage(final Message msg) { switch (msg.what) { case TRACK_FLUSH: stats.performFlush(msg.arg1); break; case TRACK_INTEGRATION_OPERATION: //noinspection unchecked stats.performIntegrationOperation((Pair<String, Long>) msg.obj); break; default: throw new AssertionError("Unknown Stats handler message: " + msg); } } } }